package com.zm.study.common;

import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by zoulei on 2017/4/11.
 */
public class CollectionUtils {

    private CollectionUtils() {
    }

    /**
     * 列表是否为空 有一个为空即返回true
     *
     * @return 是否为空
     */
    public static boolean isEmpty(Collection collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 列表是否不为空
     *
     * @param collection
     * @return
     */
    public static boolean isNotEmpty(Collection collection) {
        return collection != null && !collection.isEmpty();
    }

    /**
     * map是否为空 有一个为空即返回true
     *
     * @return 是否为空
     */
    public static boolean isEmpty(Map map) {
        return map == null || map.isEmpty();
    }

    public static boolean isNotEmpty(Map map) {
        return map != null && !map.isEmpty();
    }

    /**
     * 列表是否为空 有一个为空即返回true
     *
     * @param args 多参数列表
     * @return 是否为空
     */
    public static boolean isEmpty(Collection collection, Collection... args) {
        if (isEmpty(collection)) {
            return true;
        }
        for (Collection arg : args) {
            if (isEmpty(arg)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 上面那个是有一个为空就返回true, 我这个是参数全部为空才返回true
     *
     * @param args 多参数列表
     * @return 是否为空
     */
    public static boolean isAllEmpty(Collection collection, Collection... args) {
        if (!isEmpty(collection)) {
            return false;
        }
        for (Collection arg : args) {
            if (!isEmpty(arg)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 取数组中第一个值 如果为空 则用默认值
     *
     * @param list 列表
     * @param <T>  泛型
     * @return 第一个值
     */
    public static <T> T getFirst(List<T> list, T defaultValue) {
        if (isEmpty(list)) {
            return defaultValue;
        }
        return list.get(0);
    }

    /**
     * 取数组中最后一个值 如果为空 则用默认值
     *
     * @param list 列表
     * @param <T>  泛型
     * @return 第一个值
     */
    public static <T> T getLast(List<T> list, T defaultValue) {
        if (isEmpty(list)) {
            return defaultValue;
        }
        return list.get(list.size()-1);
    }

    /**
     * 根据某一个属性建立一个list 多用于id
     *
     * @param tList    数据源list
     * @param function 获取某属性的方法
     * @param <Source> 数据源泛型
     * @param <Result> 转化后的泛型
     * @return 新list
     */
    public static <Source, Result> List<Result> listNotNullField(List<Source> tList, Function<Source, Result> function) {
        if (isEmpty(tList) || function == null) {
            return Collections.emptyList();
        }
        List<Result> sList = new ArrayList<>();
        for (Source source : tList) {
            if (source != null) {
                Result result = function.transferTo(source);
                if (result == null || sList.contains(result)) {
                    continue;
                }
                sList.add(result);
            }
        }
        return sList;
    }

    public static <KEY, T> void addValueToListInMap(Map<KEY, List<T>> map, KEY key, T t) {
        List<T> list = map.get(key);
        if (list == null) {
            list = new ArrayList<>();
            list.add(t);
            map.put(key, list);
        } else {
            list.add(t);
        }
    }

    /**
     * 合并列表产生一个新列表
     * 并去除重复元素
     */
    public static <T> List<T> combineRemoveDuplicates(List<T> first, List<T> second) {
        return ImmutableSet.copyOf(
                Iterables.filter(
                        Lists.newArrayList(Iterables.concat(first, second))
                        , Predicates.not(Predicates.isNull())))
                .asList();
    }

    /**
     * 根据某一个属性建立一个list 多用于id
     *
     * @param tArray   数据源list
     * @param function 获取某属性的方法
     * @param <Source> 数据源泛型
     * @param <Result> 转化后的泛型
     * @return 新list
     */
    public static <Source, Result> List<Result> listNotNullField(Source[] tArray, Function<Source, Result> function) {
        if (tArray == null || function == null) {
            return Collections.emptyList();
        }
        return listNotNullField(Arrays.asList(tArray), function);
    }

    /**
     * 过滤list 生成新list
     *
     * @param tList         数据源list
     * @param attributeWith 获取某属性的方法
     * @param <T>           数据源泛型
     * @return 新list
     */
    public static <T> List<T> filter(List<T> tList, Transfer<T> attributeWith) {
        if (isEmpty(tList) || attributeWith == null) {
            return Collections.emptyList();
        }

        List<T> resultList = Lists.newArrayList();
        for (T t : tList) {
            if (attributeWith.filter(t)) {
                resultList.add(t);
            }
        }
        return resultList;
    }

    public static <T> T removeFirstObj(List<T> list) {
        if (isEmpty(list)) {
            throw new IllegalArgumentException();
        }
        return list.remove(0);
    }

    public interface Transfer<T> {
        boolean filter(T t);
    }


    /**
     * 获取某个对象的某个属性
     *
     * @param <T> 数据源
     * @param <D> 属性值
     */
    public interface Function<T, D> {
        /**
         * 获取某个对象的某个属性
         *
         * @param t 数据源
         * @return 属性值
         */
        D transferTo(T t);
    }

    public static <T> List<T> subList(List<T> list, int from, int to) {
        to = Math.min(list.size(), to);
        if (CollectionUtils.isEmpty(list) || from >= to) return Collections.emptyList();
        return list.subList(from, to);
    }

    /**
     * 去重
     *
     * @param arlList
     * @param <T>
     */
    public static <T> void removeDuplicate(List<T> arlList) {
        HashSet h = new HashSet(arlList);
        arlList.clear();
        arlList.addAll(h);
    }

    public static <T> T firstObj(List<T> list) throws IllegalArgumentException {
        if (isEmpty(list, new Collection[0])) {
            throw new IllegalArgumentException();
        } else {
            return list.get(0);
        }
    }

    public static String join(Iterator iterator, String separator) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;

        Object item;
        for (; iterator.hasNext(); sb.append(item)) {
            item = iterator.next();
            if (first) {
                first = false;
            } else {
                sb.append(separator);
            }
        }

        return sb.toString();
    }

    public static String join(Iterable<?> parts, String separator) {
        if (parts == null) {
            return "";
        }
        return Joiner.on(separator).join(parts);
    }

    /**
     * 拷贝数组
     *
     * @param list       数组
     * @param copyObject 拷贝接口
     * @param <T>        泛型
     * @return 拷贝后的数组
     */
    public static <T> List<T> copyList(List<T> list, CopyObject<T> copyObject) {
        if (isEmpty(list) || copyObject == null) {
            return new ArrayList<>();
        }
        List<T> newList = new ArrayList<>();
        for (T t : list) {
            newList.add(copyObject.copy(t));
        }
        return newList;
    }


    /**
     * 复制对象
     *
     * @param <T> 泛型
     */
    public interface CopyObject<T> {
        /**
         * 复制一个对象
         *
         * @param source 源对象
         * @return 复制后的对象
         */
        T copy(T source);
    }

    /**
     * transfer list into map
     * @param list
     * @param fieldName4Key
     * @return map
     *
     * @date 2016-9-16 12:58:53
     */
    public static <K, V> Map<K, V> list2Map2(List<V> list, String fieldName4Key, Class<V> c) {
        Map<K, V> map = new HashMap<K, V>();
        if (list != null) {
            try {
                PropertyDescriptor propDesc = new PropertyDescriptor(fieldName4Key, c);
                Method methodGetKey = propDesc.getReadMethod();
                for (int i = 0; i < list.size(); i++) {
                    V value = list.get(i);
                    @SuppressWarnings("unchecked")
                    K key = (K) methodGetKey.invoke(list.get(i));
                    map.put(key, value);
                }
            } catch (Exception e) {
                throw new IllegalArgumentException("field can't match the key!");
            }
        }

        return map;
    }

    public static <K, V> Map<K, V> list2Map3(List<V> list, String keyMethodName, Class<V> c) {
        Map<K, V> map = new HashMap<K, V>();
        if (list != null) {
            try {
                Method methodGetKey = c.getMethod(keyMethodName);
                for (int i = 0; i < list.size(); i++) {
                    V value = list.get(i);
                    @SuppressWarnings("unchecked")
                    K key = (K) methodGetKey.invoke(list.get(i));
                    map.put(key, value);
                }
            } catch (Exception e) {
                throw new IllegalArgumentException("field can't match the key!");
            }
        }

        return map;
    }

    public static <K, U> Map<K, U> list2Map4(List list, String keyMethodName, Class c, String valMethodName) {
        Map<K, U> map = new HashMap<K, U>();
        if (list != null) {
            try {
                Method methodGetKey = c.getMethod(keyMethodName);
                Method methodGetval = c.getMethod(valMethodName);
                for (int i = 0; i < list.size(); i++) {
                    @SuppressWarnings("unchecked")
                    K key = (K) methodGetKey.invoke(list.get(i));
                    U value = (U) methodGetval.invoke(list.get(i));
                    map.put(key, value);
                }
            } catch (Exception e) {
                throw new IllegalArgumentException("field can't match the key!");
            }
        }

        return map;
    }

   /* public static void main(String[] args) {
        List<JgUser> jgUsers = new ArrayList<>();

        JgUser jgUser = new JgUser();

        jgUser.setJgId("1");
        jgUser.setFullname("第一个");
        jgUsers.add(jgUser);

        JgUser jgUser2 = new JgUser();

        jgUser2.setJgId("2");
        jgUser2.setFullname("滴二个");
        jgUsers.add(jgUser2);

        Map<String,String> map =CollectionUtils.list2Map4(jgUsers, "getJgId", JgUser.class, "getFullname");
        System.out.println(map);


    }*/

    /**
     * 取数组中一个属性的值赋予另一个属性上
     *
     * @param list 列表
     * @param <T>  泛型
     * @param setstr  set赋予
     * @param getstr  get获取
     * @return list=CollectionUtils.getListsettoget(list, "dictionaryCn", "dictionaryEn");
     */
    public static <T> List<T> getListsettoget(List<T> list, String setstr, String getstr) {
        if (isNotEmpty(list)) {
            for(int i=0;i<list.size();i++){
            	T t=(T)list.get(i);
            	try {
            		Field f = t.getClass().getDeclaredField(setstr);
            		Field f1 = t.getClass().getDeclaredField(getstr);
	                f.setAccessible(true);
	                f1.setAccessible(true);
	                String mm=(String)f1.get(t);
	                f.set(t, mm);
            	}catch (Exception e) {
                    continue;
                }
            }
        }
        return list;
    }

}